/*
 * @Author: hx 2542123711@QQ.com
 * @Date: 2024-12-11 19:59:43
 * @LastEditors: hx 2542123711@QQ.com
 * @LastEditTime: 2024-12-15 16:54:47
 * @FilePath: /class_thread/thread-cp/blockqueue.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<queue>

using namespace std;

int defaultmax = 5;

template<class T>
class blockqueue
{
public:
    blockqueue(int max = defaultmax)
    {
        _max = max;
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&p_cond, nullptr);
        pthread_cond_init(&c_cond, nullptr);
    }

    //消费者
    T pop()
    {
        pthread_mutex_lock(&_mutex);
        while(_max == 0)
        {
            pthread_cond_wait(&c_cond, &_mutex);
        }
        T data = _q.front();
        _q.pop();

        //消费者拿到数据后，容器一定有一个空位置给生产者生产，所以这个时候可以唤醒生产者
        pthread_cond_signal(&p_cond);
        pthread_mutex_unlock(&_mutex);

        return data;
    }

    //生产者
    void push(const T& data)
    {
        pthread_mutex_lock(&_mutex);
        //如果队列满了，则不满足插入条件，所以让线程去生产者阻塞队列等待
        while(_max == _q.size())
        {
            pthread_cond_wait(&p_cond, &_mutex);
        }

        _q.push(data);
        
        //生产者产生数据后容器内部一定有数据，所以可以唤醒消费队列
        pthread_cond_signal(&c_cond);
        pthread_mutex_unlock(&_mutex);
    }

    ~blockqueue()
    {
        _max = 0;
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&c_cond);
        pthread_cond_destroy(&p_cond);
    }
private:
    queue<T> _q;
    int _max;

    pthread_mutex_t _mutex;
    pthread_cond_t p_cond;//生产者队列
    pthread_cond_t c_cond;//消费者队列
};